/*
 * @Author       : wfl
 * @LastEditors: qiye
 * @description  :
 * @updateInfo   :
 * @Date         : 2023-02-24 16:08:34
 * @LastEditTime: 2023-12-14 18:26:15
 */
import { ikStore, ikTree, paramType, passwordEncry } from 'iking-utils'
import { ElMessage } from 'element-plus'
import router from '@g/router/index'
import api from '@g/api'
import type { ApiModel } from '@g/types/global'
import { userApi } from '@main/apis/user'
import { menuApi } from '@main/apis/menu'
import { loginApi } from '@main/apis/login'
import { ELoginType } from '@main/views/login/login-type'
import { tenantApi } from '@main/apis/tenant'
import { systemConfig } from '../../../system.config'
import useSocketStore from './socket'
import useSettingsStore from './settings'
import useMenuStore from './menu'
import useRouteStore from './route'
import useTabbarStore from './tabbar'

const { remberRoute } = systemConfig

const useUserStore = defineStore(
  // 唯一ID
  'user',
  () => {
    const tabbarStore = useTabbarStore()
    const routeStore = useRouteStore()
    const menuStore = useMenuStore()
    const settingStore = useSettingsStore()
    const socketStore = useSocketStore()

    const account = ref(ikStore.local.getItem(ELocal.ACCOUNT) ?? '')
    const token = ref(ikStore.local.getItem(ELocal.TOKEN) ?? '')
    const failure_time = ref(ikStore.local.getItem(ELocal.FAILURE_TIME) ?? '')
    const permissions = ref<string[]>([])
    const userInfo = ref(ikStore.local.getItem(ELocal.USER_INFO) ?? '')
    const pwdVisible = ref(Boolean(Number(ikStore.local.getItem(ELocal.PWD_VISIBLE) || 0)))
    const pwdType = ref('timeout')
    const settingId = ref(ikStore.local.getItem(ELocal.SETTING_ID) ?? '')
    const tenant = ref(ikStore.local.getItem(ELocal.TENANT) ?? '')
    const showTenant = ref(false)

    /** v2 begin */
    // 当前域
    const xDomain = ref(ikStore.local.getItem('x_domain'))
    // 当前服务版本
    const serverVersion = ref(ikStore.local.getItem(ELocal.SERVER_VERSION))
    // 当前应用标识
    const xApp = ref(ikStore.local.getItem('x_app'))
    // 身份列表
    const categoryCodes = ref(ikStore.local.getItem('category_codes'))
    /** v2 end */
    const organiza = ref(ikStore.local.getItem(ELocal.ORGANIZA) || {
      select: '',
      list: []
    })

    watch(
      () => settingStore.settings,
      (val: any) => {
        const sett = {
          userId: userInfo.value.id,
          configInfoList: [
            {
              value: JSON.stringify(val),
              type: 'THEME'
            },
            {
              type: 'LANGUAGE',
              value: val?.app?.defaultLang === 'zh-cn' ? 'zh-CN' : 'en-US'
            }
          ]
        }
        settingId.value && ((sett as any).id = settingId.value)
        setUserSetting(sett as any)
      },
      { deep: true }
    )

    const isLogin = computed(() => {
      if (serverVersion.value === '1') {
        let retn = false
        if (token.value) {
          // 如果前端需要判断token过期时间，则放开以下代码
          // if (new Date().getTime() < parseInt(failure_time.value) * 60 * 1000)
          if (tenant.value)
            retn = true
        }
        return retn
      }
      else if (serverVersion.value === '2') {
        const defaultDomain = getDefaultXDomain()
        if (['PLATFORM_MANAGEMENT', 'DEV_CENTER'].includes(defaultDomain)) {
          // 是平台管理员、开发人员，则只判断 token
          if (token.value) {
            //
            return true
          }
        }
        else if (['TENANT_SERVICE'].includes(defaultDomain)) {
          // 是租户、普通人员，则需要判断当前租户信息
          if (tenant.value) {
            //
            return true
          }
        }
        else {
          if (token.value) {
            //
            return true
          }
        }
      }
      return false
    }
    )

    // 后端服务版本
    const serviceVersion = computed(() => serverVersion.value)

    const isLoginFn = () => {
      if (ikStore.local.getItem(ELocal.SERVER_VERSION) === '1') {
        let retn = false
        if (token.value) {
        // 如果前端需要判断token过期时间，则放开以下代码
        // if (new Date().getTime() < parseInt(failure_time.value) * 60 * 1000)
          if (tenant.value)
            retn = true
        }
        return retn
      }
      else if (ikStore.local.getItem(ELocal.SERVER_VERSION) === '2') {
        const defaultDomain = getDefaultXDomain()
        if (['PLATFORM_MANAGEMENT', 'DEV_CENTER'].includes(defaultDomain)) {
          // 是平台管理员、开发人员，则只判断 token
          if (token.value) {
            //
            return true
          }
        }
        else if (['TENANT_SERVICE'].includes(defaultDomain)) {
          // 是租户、普通人员，则需要判断当前租户信息
          if (tenant.value) {
            //
            return true
          }
        }
        else {
          if (token.value) {
            //
            return true
          }
        }
      }
      return false
    }

    const isLoginOld = computed(() => {
      if (ikStore.local.getItem(ELocal.SERVER_VERSION) === '1') {
        let retn = false
        if (token.value) {
        // 如果前端需要判断token过期时间，则放开以下代码
        // if (new Date().getTime() < parseInt(failure_time.value) * 60 * 1000)
          if (tenant.value)
            retn = true
        }
        return retn
      }
      else if (ikStore.local.getItem(ELocal.SERVER_VERSION) === '2') {
        if (token.value || ikStore.local.getItem('token'))
          return true
      }
      return false
    })

    const handleLoginRes = async (res: { msg: string; data: any;success: boolean; }, type: string) => {
      const { msg, data, success } = res
      if (!success) {
        ElMessage.warning(msg)
        return
      }
      if (success) {
        // 系统右上角用户名
        account.value = data.name
        token.value = data.token
        failure_time.value = data.expire
      }
      updatePwdVisible(data?.passwordExpired || false)

      if (success && type === ELoginType.密码登录) {
        await ikStore.local.setItem(ELocal.TOKEN, data.token)
        ikStore.local.setItem(ELocal.ACCOUNT, data.name)
        ikStore.local.setItem(
          ELocal.FAILURE_TIME,
          new Date().getTime() + parseInt(data.expire || 99999) * 1000 * 60
        )
        ElMessage.success(msg)
      }

      // 当登录响应存在 'categoryCodes' 属性时，后端服务版本为 v2
      if (success) {
        if (data.categoryCodes) {
          ikStore.local.setItem(ELocal.SERVER_VERSION, '2')
          ikStore.local.setItem(ELocal.CATEGORY_CODES, data.categoryCodes)
          categoryCodes.value = data.categoryCodes
          serverVersion.value = '2'
          resetXDomain()
        }
        else {
          ikStore.local.setItem(ELocal.SERVER_VERSION, '1')
          serverVersion.value = '1'
        }
      }
      loginApi.getPageCssFilter().then((res: any) => {
        ikStore.local.setItem(ELocal.GRRY, res?.data ?? 1)
      })
      // 获取用户详细信息userInfo
      await getUserInfo(data.id)
      // userInfo.value = data
      // ikStore.local.setItem(ELocal.USER_INFO, data)
      return res
    }

    const buildTokenAutoLoginRes = (token: string | undefined) => {
      return {
        code: 200,
        success: true,
        msg: '登录成功',
        pages: 0,
        total: 0,
        data: {
          name: '',
          token,
          expire: 0
        }
      }
    }

    const userTenant = async (params: any) => {
      await tenantApi.addUserTenant(params)
    }
    const getLoginUser = async () => {
      await tenantApi.getLoginUser()
    }

    const queryAllDic = async () => {
      try {
        await getUserSetting()
        await getAllDiction()
      }
      catch (error) {
        console.info('error', error)
      }
    }

    const autoLoginNext = async () => {
      const res = await queryTenant()
      const tenantList = ref<any>(null)
      if (res?.success) {
        tenantList.value = res?.data || null
        if (res?.data?.tenantList?.length === 1) {
          if (res?.data?.tenantList[0].normal) {
            ikStore.local.setItem(ELocal.TENANT, res?.data?.tenantList[0])
            tenant.value = res?.data?.tenantList[0]
            await userTenant(res?.data?.tenantList[0]?.code)
            await getLoginUser()
            await queryAllDic()
            if (!showTenant.value) {
              // router.push(redirect.value)
              return
            }
          }
          else {
            showTenant.value = true
          }
        }
        if (res?.data?.tenantList?.length > 1) {
          const loginTenant = res?.data?.tenantList.find(
            (item: any) => item.recent === true
          )
          if (loginTenant) {
            tenant.value = loginTenant
            ikStore.local.setItem(ELocal.TENANT, loginTenant)
            await userTenant(loginTenant?.code)
            await getLoginUser()
            await queryAllDic()
            if (!showTenant.value) {
              // router.push(redirect.value)
              return
            }
          }
        }
        showTenant.value = true
      }
      else {
        // res?.msg && msgError(res?.msg)
        showTenant.value = false
      }
    }
    async function autoLogin(token: string, to: any) {
      const res = await login({ token }, ELoginType.Token自动登录)
      await autoLoginNext()
      if (res?.success)
        router.push(to.path)
    }
    // 登录
    async function login(
      param: {
        account?: string
        password?: string
        phone?: string
        captcha?: string
        token?: string
      },
      type: string
    ) {
      let res: ApiModel = {
        msg: '',
        data: null,
        code: 0,
        pages: 0,
        success: false,
        total: 0
      }
      switch (type) {
        case ELoginType.Token自动登录:
          res = buildTokenAutoLoginRes(param.token)
          break
        case ELoginType.密码登录:
          res = await loginApi.login(
            {
              credentialName: param.account,
              password: passwordEncry(
                param.password || '',
                '1234567890000000',
                {
                  encode: 'hex'
                }
              ).AES.encrypt()
            },
            {
              headers: {
                'X-PASSWORD-ENCRYPT': 'encrypt'
              }
            }
          )
          break
        case ELoginType.短信登录:
          // 短信登录参数
          res = await loginApi.login(
            {
              phone: param.phone,
              smsVerifyCode: param.captcha
            },
            {
              headers: {
                'X-PASSWORD-ENCRYPT': 'encrypt'
              }
            }
          )
          break
        case ELoginType.微信登录:
          // 微信登录参数
          res = await loginApi.login(
            {
              wechatMiniOpenId: ''
            },
            {}
          )
          break
        case ELoginType.钉钉登录:
          // 钉钉登录参数
          break
        default:
          break
      }
      return handleLoginRes(res, type)
    }
    //
    function clearCache() {
      try {
        routeStore.removeRoutes()
        // routeStore.isGenerate = false
        ikStore.local.removeItem('account')
        ikStore.local.removeItem('token')
        ikStore.local.removeItem('failure_time')
        ikStore.local.removeItem('user_info')
        ikStore.local.removeItem('tenant')
        // v2 相关缓存 begin
        xDomain.value = ''
        ikStore.local.removeItem('x_domain')
        ikStore.local.removeItem(ELocal.SERVER_VERSION)
        ikStore.local.removeItem(ELocal.CATEGORY_CODES)
        removeXApp()
        // v2 相关缓存 end
        account.value = ''
        token.value = ''
        failure_time.value = ''
        permissions.value = []
        tenant.value = null
        tabbarStore.clean()
        menuStore.setActived(0)
      }
      catch (error) {
        console.info('error: ', error)
      }
    }
    // 登出
    async function logout() {
      const { success } = await loginApi.loginOut()
      if (success) {
        router.push({
          path: '/login',
          query: remberRoute
            ? {
                redirect:
              router.currentRoute.value.path !== '/login'
                ? router.currentRoute.value.fullPath
                : undefined
              }
            : {}
        })
      }
      clearCache()
    }
    // 获取用户租户信息
    async function queryTenant() {
      if (!token.value) {
        //
        return null
      }

      let res = null
      if (ikStore.local.getItem(ELocal.SERVER_VERSION) === '1') {
        // v1
        res = await tenantApi.queryTenantList()
      }
      else if (ikStore.local.getItem(ELocal.SERVER_VERSION) === '2') {
        // v2
        res = await tenantApi.queryTenantListV2()
      }
      return res
    }
    // 获取用户信息 通过
    async function getUserInfo(id: string) {
      if (!token.value)
        return null
      const { success, data } = await loginApi.getUserInfo(id)
      if (success) {
        userInfo.value = data
        if (!account.value)
          account.value = data.name
        data && ikStore.local.setItem(ELocal.USER_INFO, data)
        organiza.value = {
          select: data.organizationIds?.[0] || '',
          list: data.organizations
        }
        ikStore.local.setItem(ELocal.ORGANIZA, organiza.value)
        try {
          socketStore.createSocket()
        }
        catch (error) {

        }
      }
    }

    // 获取字典
    async function getAllDiction() {
      const { success, msg, data } = await menuApi.getAllDiction()
      if (success) {
        const fa: Set<string> = new Set(
          data.map((item: { dictCode: string; }) => item?.dictCode)
        )
        for (const i of fa) data.push({ id: i, name: i })

        const dict: { [key: string]: any; } = {}
        const tree = ikTree.listToTree(data, { id: 'id', pid: 'dictCode' })
        for (const i of fa) dict[i] = tree.find(f => f.id === i)?.children
        ikStore.local.setItem(ELocal.DICTIONARY, dict)
      }
      else { ElMessage.warning(msg) }
    }

    // 获取我的权限
    async function getPermissions() {
      // 通过 mock 获取权限
      const res = await api.get('member/permission', {
        baseURL: '/mock/',
        params: {
          account: account.value
        }
      })
      permissions.value = res.data.permissions
      return permissions.value
    }
    // 修改密码
    async function editPassword(data: {
      password: string
      newpassword: string
    }) {
      await api.post(
        'member/edit/password',
        {
          account: account.value,
          password: data.password,
          newpassword: data.newpassword
        },
        {
          baseURL: '/mock/'
        }
      )
    }
    // 更新密码框状态
    function updatePwdVisible(bool: boolean, type = 'timeout') {
      pwdType.value = type
      pwdVisible.value = Boolean(bool)
      ikStore.local.setItem(ELocal.PWD_VISIBLE, bool ? 1 : 0)
    }
    // 获取并应用用户配置
    async function getUserSetting() {
      const { success, data, msg } = await userApi.getSetting()
      if (success && data?.configInfoList?.length) {
        const dataValue = data?.configInfoList?.find((item: any) => item.type === 'THEME')
        const sett = JSON.parse(dataValue?.value || '')
        if (!paramType.isObject(sett)) {
          console.warn('用户配置错误', sett)
          return
        }
        settingStore.updateSettings(sett)
        settingId.value = dataValue?.id
        ikStore.local.setItem(ELocal.SETTING, sett)
      }
      !success && console.warn(msg)
    }
    // 保存用户配置
    async function setUserSetting(config: {
      id?: string
      userId: string
      type: 'THEME' | 'LANGUAGE'
      value: string
    }) {
      const { success, msg } = await userApi.setSetting({
        ...config,
        global: false
      })
      !success && console.warn(msg)
      try {
        ikStore.local.setItem(ELocal.SETTING, JSON.parse((config as any)?.configInfoList?.find((item: any) => item.type === 'THEME')?.value || ''))
      }
      catch (error) {
      }
    }

    /** 域 begin */
    // 当去用户的默认域
    function getDefaultXDomain() {
      const categoryCodes = ikStore.local.getItem(ELocal.CATEGORY_CODES) ?? []
      if (categoryCodes.includes('PLATFORM_ADMINISTRATOR')) {
        // 平台管理员
        return 'PLATFORM_MANAGEMENT'
      }
      else if (categoryCodes.includes('TENANT_ADMINISTRATOR') || categoryCodes.includes('NORMAL_USER')) {
        // 租户
        return 'TENANT_SERVICE'
      }
      else if (categoryCodes.includes('MAINTAINER')) {
        // 运维人员
        return 'MAINTENANCE'
      }
      else if (categoryCodes.includes('DEVELOPER')) {
        // 开发人员
        return 'DEV_CENTER'
      }
      else {
        return ''
      }
    }

    // 获取域
    function getXDomain() {
      if (!xDomain.value) {
        // 设置默认值
        setXDomain(getDefaultXDomain())
      }
      return xDomain.value
    }

    function setXDomain(value: string) {
      ikStore.local.setItem('x_domain', value)
      xDomain.value = value
    }

    // 获取应用标识
    function getXApp() {
      if (!xApp.value) {
        //
        xApp.value = ikStore.local.getItem('x_app')
      }
      return xApp.value
    }
    // 设置应用标识
    function setXApp(value: string) {
      ikStore.local.setItem('x_app', value)
      xApp.value = value
    }
    // 移除应用标识
    function removeXApp() {
      ikStore.local.removeItem('x_app')
      xApp.value = ''
    }
    // 重置域
    function resetXDomain() {
      setXDomain(getDefaultXDomain())
      setXApp('')
    }
    // 重置域和域对应下的路由
    async function resetXDomainAndMenu() {
      resetXDomain()
      await routeStore.refreshBackendMenu()
    }
    /** 域 end */

    return {
      account,
      token,
      permissions,
      isLogin,
      userInfo,
      pwdVisible,
      pwdType,
      tenant,
      showTenant,
      serviceVersion,
      categoryCodes,
      organiza,
      login,
      autoLogin,
      logout,
      getPermissions,
      editPassword,
      updatePwdVisible,
      clearCache,
      getUserSetting,
      setUserSetting,
      queryTenant,
      getAllDiction,
      queryAllDic,
      getXDomain,
      setXDomain,
      getXApp,
      setXApp,
      getDefaultXDomain,
      isLoginFn,
      resetXDomain,
      resetXDomainAndMenu
    }
  }
)

export default useUserStore
